package com.raincat.tools.nettools;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;

import androidx.core.content.FileProvider;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;

import com.raincat.tools.notificationtools.NotificationConfig;

import java.io.File;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.DecimalFormat;

/**
 * 下载服务
 *
 * @author 躲雨的猫
 */
public class DownloadService extends Service {
    /**
     * 下载开始通知
     */
    public static final String DOWNLOAD_START = "download_start";
    /**
     * 下载进度通知
     */
    public static final String DOWNLOAD_STATUS = "download_status";
    /**
     * 下载失败通知
     */
    public static final String DOWNLOAD_FAILURE = "download_failure";
    /**
     * 下载成功通知
     */
    public static final String DOWNLOAD_SUCCESS = "download_success";
    /**
     * 占用通知标识
     */
    private static final int APP_ID = 250;

    private Context context = null;
    private int resId = 0;

    private HttpURLConnection connection = null;
    private int fileSize = 0;
    private String fileName = "";


    private LocalBroadcastManager localBroadcastManager;

    Handler mHandler = new Handler() {
        public void handleMessage(Message msg) {
            if (msg.what == 1) {// 更新进度
                int length = msg.arg1;
                DecimalFormat df = new DecimalFormat("#.##");
                String content = "进度：" + df.format(length / 1024.0 / 1024.0) + "MB/" + df.format(fileSize / 1024.0 / 1024.0) + "MB";
                if (resId != 0)
                    NotificationConfig.getInstance(context).sendLockNotification(context, APP_ID, fileName + "下载中...", fileName, content, resId, true, fileSize, length);
                Intent intent = new Intent(DOWNLOAD_STATUS);
                intent.putExtra("length", length);
                localBroadcastManager.sendBroadcast(intent);
            } else if (msg.what == 2) {
                String url = (String) msg.obj;
                if (url.indexOf(".apk") != -1)
                    context.startActivity(installationProgram(url));
                Intent intent = new Intent(DOWNLOAD_SUCCESS);
                intent.putExtra("path", url);
                localBroadcastManager.sendBroadcast(intent);
                stopSelf();
            } else {// 下载异常
                localBroadcastManager.sendBroadcast(new Intent(DOWNLOAD_FAILURE));
                stopSelf();
            }
        }
    };

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        context = DownloadService.this;
        localBroadcastManager = LocalBroadcastManager.getInstance(context);

        String url = intent.getStringExtra("url");
        resId = intent.getIntExtra("resId", 0);

        if (url == null || url.length() == 0) {
            sendMessage(3, url, 0);
        }

        startDownload(context, url);
        return Service.START_STICKY;
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    private void startDownload(final Context context, final String urlStr) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                String downloadPath = Environment.getExternalStorageDirectory() + "/Android/data/" + context.getPackageName() + "/files/Download";
                File dir = new File(downloadPath);
                if (!dir.exists()) {
                    dir.mkdirs();
                }
                fileName = urlStr.substring(urlStr.lastIndexOf("/") + 1);
                downloadPath = downloadPath + "/" + fileName;

                RandomAccessFile randomAccessFile = null;
                InputStream is = null;
                try {
                    URL url = new URL(urlStr);
                    HttpURLConnection Connection = (HttpURLConnection) url.openConnection();
                    Connection.setConnectTimeout(5000);
                    Connection.setRequestMethod("GET");
                    fileSize = Connection.getContentLength();
                    Connection.disconnect();

                    //下载开始
                    Intent intent = new Intent(DOWNLOAD_START);
                    intent.putExtra("size", fileSize);
                    localBroadcastManager.sendBroadcast(intent);

                    connection = (HttpURLConnection) url.openConnection();
                    connection.setDoInput(true);
                    connection.setRequestMethod("GET");
                    connection.setReadTimeout(5000);
                    connection.setUseCaches(false);
                    connection.setInstanceFollowRedirects(true);
                    connection.setChunkedStreamingMode(0);//设置超时不自动重试

                    // 设置范围，格式为Range：bytes x-y;
                    connection.setRequestProperty("Range", "bytes=" + 0 + "-" + "");

                    randomAccessFile = new RandomAccessFile(downloadPath, "rwd");
                    randomAccessFile.seek(0);
                    // 将要下载的文件写到保存在保存路径下的文件
                    is = connection.getInputStream();
                    byte[] buffer = new byte[4096];
                    int length;
                    int index = 0;
                    int count = 0;
                    while ((length = is.read(buffer)) != -1) {
                        randomAccessFile.write(buffer, 0, length);
                        count += length;

                        if (index >= 87) {
                            // 用消息将下载信息传给进度条，对进度条进行更新
                            sendMessage(1, urlStr, count);
                            index = 0;
                        }
                        index++;
                    }
                    // 用消息将下载信息传给进度条，下载完成
                    sendMessage(2, downloadPath, count);
                } catch (Exception e) {
                    e.printStackTrace();
                    sendMessage(3, urlStr, 0);
                } finally {
                    try {
                        if (is != null)
                            is.close();
                        if (randomAccessFile != null)
                            randomAccessFile.close();
                        if (connection != null)
                            connection.disconnect();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }

    // 封装message
    private void sendMessage(int what, String url, int count) {
        Message message = Message.obtain();
        message.what = what;
        message.obj = url;
        message.arg1 = count;
        mHandler.sendMessage(message);
    }

    /**
     * 封装APP安装intent
     *
     * @param filePath 路径
     */
    private Intent installationProgram(String filePath) {
        Intent intent = new Intent("android.intent.action.VIEW");
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        File file = new File(filePath);
        Uri data;
        if (Build.VERSION.SDK_INT >= 24) {
            data = FileProvider.getUriForFile(this.context, context.getPackageName() + ".fileProvider", file);
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        } else {
            data = Uri.fromFile(file);
        }
        intent.setDataAndType(data, "application/vnd.android.package-archive");
        return intent;
    }

    @Override
    public void onDestroy() {
        NotificationConfig.getInstance(context).cancelNotification(APP_ID);
        try {
            if (connection != null)
                connection.disconnect();
        } catch (Exception e) {
            e.printStackTrace();
        }
        super.onDestroy();
    }
}